package com.basic.business.finance.service.impl;

import com.basic.business.finance.domain.*;
import com.basic.business.finance.mapper.TMoneyDetailsMapper;
import com.basic.business.finance.mapper.TMoneyMainMapper;
import com.basic.business.finance.mapper.TMoneySummaryMapper;
import com.basic.business.finance.service.ITMoneySummaryService;
import com.basic.common.constant.CacheConstants;
import com.basic.common.core.redis.RedisCacheUtils;
import com.basic.common.core.service.impl.BaseServiceImpl;
import com.basic.common.enums.BusinessStatus;
import com.basic.common.utils.StringUtils;
import com.basic.common.websocket.WebSocketUsers;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service
public class TMoneySummaryServiceImpl extends BaseServiceImpl<TMoneySummaryMapper, TMoneySummary> implements ITMoneySummaryService {

    @Resource
    private TMoneyDetailsMapper detailsMapper;

    @Resource
    private TMoneySummaryMapper summaryMapper;

    @Resource
    private TMoneyMainMapper mainMapper;


    @Override
    public void classifyMoney(TMoneyMain moneyMain) {
        try {
            List<TMoneyRules> rulesRedis = RedisCacheUtils.getCacheObject(CacheConstants.MONEY_RULES_REDIS_KEY);
            ExecutorService executor = Executors.newFixedThreadPool(10);

            // 根据mainId获取账单数据
            List<TMoneyDetails> detailsList = detailsMapper.getByMainId(moneyMain.getId());
            // 将集合拆分成500一个的小集合，并用多线程处理
            List<List<TMoneyDetails>> splitList = Lists.partition(detailsList, 500);
            CountDownLatch latch = new CountDownLatch(splitList.size());
            // 遍历拆分后的小集合
            for (List<TMoneyDetails> subList : splitList) {
                executor.execute(() -> {
                    try {
                        // 处理每个子集合的业务逻辑
                        processSubList(subList, rulesRedis, moneyMain.getRulePlatform()); // 替换为实际处理方法
                    } finally {
                        // 每个线程完成后减少计数器
                        latch.countDown();
                    }
                });
            }
            latch.await();
            executor.shutdown();
            moneyMain.setStatus("4");
        } catch (Exception e) {
            moneyMain.setStatus("5");
        } finally {
            moneyMain.setId(moneyMain.getId());
            mainMapper.update(moneyMain);
            // 通过websocket发送通知
            WebSocketUsers.sendMessageToUserByText(moneyMain.getUserId(),  moneyMain.getExcelName() + " 账单处理完毕", BusinessStatus.SUCCESS);
        }
    }

    @Override
    public void deleteMainIds(Object[] ids) {
        summaryMapper.deleteMainIds(ids);
    }

    /**
     * 处理子集合的业务逻辑
     */
    public void processSubList(List<TMoneyDetails> detailsList, List<TMoneyRules> rulesRedis, String rulePlatform) {
        // 1. 预初始化结果集（根据业务特点，1个detail对应1个summary）
        List<TMoneySummary> summaryList = new ArrayList<>(detailsList.size());

        // 2. 预处理规则（使用Java8 Stream API优化）
        Map<String, List<TMoneyRules>> rulesByBusinessType = rulesRedis.stream()
                .filter(rule -> rulePlatform.equals(rule.getRulePlatform()))
                .sorted(Comparator.comparingInt(TMoneyRules::getSort))
                .collect(Collectors.groupingBy(TMoneyRules::getBusinessType));

        // 3. 优化后的处理逻辑
        for (TMoneyDetails details : detailsList) {
            TMoneySummary summary = createSummary(details);
            matchRules(details, summary, rulesByBusinessType);
            summaryList.add(summary);
        }

        // 4. 批量入库（保持原有逻辑）
        if (!summaryList.isEmpty()) {
            summaryMapper.batchInsert(summaryList);
        }
    }

    private TMoneySummary createSummary(TMoneyDetails details) {
        TMoneySummary summary = new TMoneySummary();
        summary.setMainId(details.getMainId());
        summary.setDetailsId(details.getId());
        return summary;
    }

    private void matchRules(TMoneyDetails details, TMoneySummary summary,
                            Map<String, List<TMoneyRules>> rulesByBusinessType) {
        List<TMoneyRules> matchedRules = rulesByBusinessType.get(details.getBusinessType());

        if (matchedRules != null) {
            // 寻找匹配的规则（包括rule和matchContent为空的规则）
            Optional<TMoneyRules> matchedRule = matchedRules.stream()
                    .filter(rule -> {
                        // 如果rule和matchContent都为空，视为匹配
                        if (StringUtils.isEmpty(rule.getRule()) &&
                                StringUtils.isEmpty(rule.getMatchContent())) {
                            return true;
                        }
                        // 否则按正常规则匹配
                        return isRuleMatch(details, rule);
                    })
                    .findFirst();

            if (matchedRule.isPresent()) {
                TMoneyRules rule = matchedRule.get();
                // 设置规则ID，即使rule和matchContent为空
                summary.setRuleId(rule.getId());

                // 如果rule和matchContent为空，将金额相加
                if (StringUtils.isEmpty(rule.getRule()) &&
                        StringUtils.isEmpty(rule.getMatchContent())) {
                    summary.setAmount(details.getIncomeAmount().add(details.getExpenditureAmount()));
                } else {
                    // 否则按正常规则处理
                    setMatchedAmount(summary, details, rule);
                }
            } else {
                setDefaultAmount(summary, details);
            }
        } else {
            setDefaultAmount(summary, details);
        }
    }

    private boolean isRuleMatch(TMoneyDetails details, TMoneyRules rule) {
        if (StringUtils.isEmpty(rule.getMatchContent())) {
            return false;
        }

        if ("black".equals(rule.getRule()) && StringUtils.isEmpty(details.getBusinessTypeRemark())){
            return "收入金额".equals(rule.getMatchContent()) || "支出金额".equals(rule.getMatchContent());
        }

        if ("only".equals(rule.getRule())) {
            return "收入金额".equals(rule.getMatchContent()) || "支出金额".equals(rule.getMatchContent());
        }

        if ("%".equals(rule.getRule())) {
            return StringUtils.contains(details.getBusinessTypeRemark(), rule.getMatchContent());
        }



        return false;
    }

    private void setMatchedAmount(TMoneySummary summary, TMoneyDetails details, TMoneyRules rule) {
        summary.setRuleId(rule.getId());
        switch (rule.getMatchContent()) {
            case "收入金额":
                summary.setAmount(details.getIncomeAmount());
                break;
            case "支出金额":
                summary.setAmount(details.getExpenditureAmount());
                break;
            default:
                summary.setAmount(details.getIncomeAmount().add(details.getExpenditureAmount()));
        }
    }

    private void setDefaultAmount(TMoneySummary summary, TMoneyDetails details) {
        summary.setAmount(details.getIncomeAmount().add(details.getExpenditureAmount()));
    }

    @Override
    public void reGenerate(TMoneyMain moneyMain) {
        // 1.状态变更为生成中
        moneyMain.setStatus("3");
        mainMapper.update(moneyMain);
        WebSocketUsers.sendMessageToUserByText(moneyMain.getUserId(),  moneyMain.getExcelName() + " 账单生成中", BusinessStatus.SUCCESS);
        // 2.删掉原来生成的
        summaryMapper.deleteMainIds(new Object[]{moneyMain.getId()});

        // 3.重新生成
        classifyMoney(moneyMain);
    }

    @Override
    public List<TMoneySummaryExport> getExportInfo(List<String> mainIds) {
        return summaryMapper.getExportInfo(mainIds);
    }


}
